package com.weilele.mvvm.utils.android_r

import android.animation.ValueAnimator
import android.graphics.Rect
import android.os.Build
import android.view.*
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.animation.PathInterpolatorCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import com.weilele.mvvm.base.helper.ILifecycleObserver
import com.weilele.mvvm.base.livedata.appCompatActivity
import kotlin.math.max

@Deprecated("使用ImeHelper2作为替代")
class ImeHelper private constructor(
    private val window: Window,
    private val enableOnApplyWindowInsetsListener: Boolean/*
                                   true:会改变状态栏，导航栏颜色
                                   false:不会改变颜色，在dialog使用，键盘无法监听
                                   */
) : ILifecycleObserver {
    companion object {
        operator fun invoke(
            fragment: Fragment, window: Window = fragment.appCompatActivity!!.window,
            enableOnApplyWindowInsetsListener: Boolean = false
        ): ImeHelper {
            return create(fragment, window, enableOnApplyWindowInsetsListener)
        }

        operator fun invoke(
            activity: AppCompatActivity, window: Window = activity.window,
            enableOnApplyWindowInsetsListener: Boolean = false
        ): ImeHelper {
            return create(activity, window, enableOnApplyWindowInsetsListener)
        }

        private fun create(
            owner: LifecycleOwner,
            window: Window,
            enableOnApplyWindowInsetsListener: Boolean = false
        ): ImeHelper {
            val helper = ImeHelper(window, enableOnApplyWindowInsetsListener)
            owner.lifecycle.addObserver(helper)
            return helper
        }
    }

    private var _imeHeight = 0
    private val outRect = Rect()
    private val contentView by lazy {
        window.getContentView()
    }
    private var _listener: Function2<Int, Int, Unit>? = null

    override fun onCreate(lifecycleOwner: LifecycleOwner) {
        super.onCreate(lifecycleOwner)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            addListener(window)
        } else {
            contentView.post {
                contentView.getWindowVisibleDisplayFrame(outRect).let {
                    noShowImeViewBottom = outRect.bottom
                }
                contentView.viewTreeObserver?.addOnGlobalLayoutListener(layoutChange)
            }
        }
    }


    override fun onDestroy(lifecycleOwner: LifecycleOwner) {
        super.onDestroy(lifecycleOwner)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            removeListener(lifecycleOwner)
        }
        _listener = null
        contentView.viewTreeObserver?.removeOnGlobalLayoutListener(layoutChange)
        lifecycleOwner.lifecycle.removeObserver(this)
    }

    private val layoutChange = ViewTreeObserver.OnGlobalLayoutListener {
        val view = contentView
        val top = outRect.top
        val bottom = outRect.bottom
        view.getWindowVisibleDisplayFrame(outRect)
        val newBottom = outRect.bottom
        val newTop = outRect.top
        if (newTop != top || newBottom != bottom) {
            if (noShowImeViewBottom != newBottom) {
                //键盘显示
                _imeHeight = noShowImeViewBottom - newBottom
                _listener?.invoke(noShowImeViewBottom - newBottom, _imeHeight)
            } else {
                //键盘隐藏
                _listener?.invoke(noShowImeViewBottom - newBottom, _imeHeight)
            }
        }
    }

    @RequiresApi(Build.VERSION_CODES.R)
    private fun addListener(window: Window?) {
        window ?: return
        //这里必须用decorView，用其他的不走回调
        val view = window.decorView
        if (autoDecorFitsSystemWindows) {
            window.setDecorFitsSystemWindows(false)
        }
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
        var isCanAnim = false
        if (enableOnApplyWindowInsetsListener) {
            view.setOnApplyWindowInsetsListener { v, insets ->
                //键盘
                if (!isCanAnim) {
                    val imeBottom = insets.getInsets(WindowInsets.Type.ime()).bottom
                    val navigationBarBottom =
                        insets.getInsets(WindowInsets.Type.navigationBars()).bottom
                    _imeHeight = imeBottom - navigationBarBottom
                    _listener?.invoke(max(imeBottom - navigationBarBottom, 0), _imeHeight)
                }
                insets
            }
        }
        //包含键盘和底部状态栏的总高度
        var imeAndNavigationBarHeight = 0
        view.setWindowInsetsAnimationCallback(object :
            WindowInsetsAnimation.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
            override fun onProgress(
                insets: WindowInsets,
                runningAnimations: MutableList<WindowInsetsAnimation>
            ): WindowInsets {
                val imeBottom = insets.getInsets(WindowInsets.Type.ime()).bottom
                val navigationBarBottom =
                    insets.getInsets(WindowInsets.Type.navigationBars()).bottom
                _imeHeight = imeAndNavigationBarHeight - navigationBarBottom
                _listener?.invoke(max(imeBottom - navigationBarBottom, 0), _imeHeight)
                return insets
            }

            override fun onPrepare(animation: WindowInsetsAnimation) {
                super.onPrepare(animation)
                isCanAnim = true
            }

            override fun onStart(
                animation: WindowInsetsAnimation,
                bounds: WindowInsetsAnimation.Bounds
            ): WindowInsetsAnimation.Bounds {
                imeAndNavigationBarHeight = bounds.upperBound.bottom
                return super.onStart(animation, bounds)
            }
        })
    }

    @RequiresApi(Build.VERSION_CODES.R)
    private fun removeListener(lifecycleOwner: LifecycleOwner) {
        if (autoDecorFitsSystemWindows) {
            window.setDecorFitsSystemWindows(true)
        }
        val view = contentView
        view.setOnApplyWindowInsetsListener(null)
        view.setWindowInsetsAnimationCallback(null)
    }

    //没有显示键盘时，rootView的bottom
    private var noShowImeViewBottom = 0

    //自动管理，有时候安卓11，键盘事件不会回调
    var autoDecorFitsSystemWindows = false


    /**
     * 如果屏幕发生变化，应该调用一下这个方法
     */
    fun reset() {
        noShowImeViewBottom = 0
    }


    fun setOnImeListener(
        listener: Function2<@ParameterName("imeOffset") Int,
                @ParameterName("imeHeight") Int, Unit>?
    ) {
        _listener = if (listener == null) {
            null
        } else {
            { imeOffset, imeHeight ->
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || enableOnApplyWindowInsetsListener) {
                    animChange(imeOffset, imeHeight, listener)
                } else {
                    listener.invoke(imeOffset, imeHeight)
                }
            }
        }
    }

    private val anim by lazy {
        ValueAnimator.ofInt().apply {
            duration = maxAnimatorDuration
//            interpolator=DecelerateInterpolator()
            interpolator = PathInterpolatorCompat.create(1f, 1f)
        }
    }
    private var lastOffSet = 0
    private val maxAnimatorDuration = 185L
    private fun animChange(
        offset: Int,
        imeHeight: Int,
        listener: (imeOffset: Int, imeHeight: Int) -> Unit
    ) {
        if (offset == lastOffSet) {
            return
        }
        anim.cancel()
        anim.removeAllUpdateListeners()
        anim.setIntValues(lastOffSet, offset)
        lastOffSet = offset
        anim.addUpdateListener {
            val value = it.animatedValue as Int
            listener.invoke(value, imeHeight)
        }
        anim.start()
    }
}